﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;

using XmlConfig;

namespace KnowHow
{
    public partial class MainForm : Form
    {
        [DllImport("User32.dll")]
        protected static extern int SetClipboardViewer(int hWndNewViewer);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

        IntPtr nextClipboardViewer;
        


        public delegate void functioncall();
        private event functioncall saveFunctionPointer;

        bool bSmall = false;
        int oldWidth;
        int oldHeight;
        
        private bool firstMonitor;
        bool treeView1HasFocus = true;
        int        treeView1SplitterDistance = 270;
            

        int        myHtmlEditor1SplitterDistance = 110;

        XmlConfigurator config;
        TreeNode openNode = null;
        TreeNode rootNode;
        // Node being dragged
        private TreeNode dragNode = null;
        // Temporary drop node for selection
        private TreeNode tempDropNode = null;
        // Timer for scrolling
        private Timer timer = new Timer();

        public MainForm()
        {
            InitializeComponent();
            nextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle);

            saveFunctionPointer += new functioncall(save);
            myHtmlEditor1.userFunctionPointer = saveFunctionPointer;

            config = new XmlConfigurator();
            myHtmlEditor1.setConfig(config);
            refreshTree();
            timer.Interval = 200;
            timer.Tick += new EventHandler(timer_Tick);

            firstMonitor = true;

            string emptyFilename = config.get("ContentPath") + "\\_empty.htm";
            copy(config.get("TemplateFile"), emptyFilename);

            splitContainer1.SplitterDistance = config.getInt("SplitterDistance", 140);
            treeView1SplitterDistance = splitContainer1.SplitterDistance; 
            myHtmlEditor1.loadFile(emptyFilename);
        }




        public void refreshTree()
        {
            openNode = null;

            treeView1.Nodes.Clear();

            string[] paths = config.getMany("ContentPath");
            //foreach (string path in config.getMany("ContentPath"))
            for (int i=paths.Length-1; i>=0; i--)
            {
                //String path = config.get("ContentPath");
                rootNode = new TreeNode(paths[i]);
                treeView1.Nodes.Add(rootNode);
                rootNode.ImageIndex = 2;
                rootNode.SelectedImageIndex = 2;
                rootNode.Tag = 1;
                rootNode.ContextMenuStrip = contextMenuStripFolder;

                PopulateTree(paths[i], rootNode);
                rootNode.Expand();
            }
        }

        public void PopulateTreeRoot(string dir)
        {
            // get the information of the directory
            DirectoryInfo directory = new DirectoryInfo(dir);
            // loop through each subdirectory
            foreach (DirectoryInfo d in directory.GetDirectories())
            {
                if (d.Name.StartsWith("_"))
                    break;
                // create a new node
                TreeNode t = new TreeNode(d.Name);
                // populate the new node recursively
                t.ImageIndex = 1;
                t.SelectedImageIndex = 1;
                PopulateTree(d.FullName, t);
                treeView1.Nodes.Add(t); // add the node to the "master" node
            }
            // lastly, loop through each file in the directory, and add these as nodes
            foreach (FileInfo f in directory.GetFiles())
            {
                if (f.Extension == ".html" && !f.Name.StartsWith("_"))
                {
                    // create a new node
                    TreeNode t = new TreeNode(f.Name.Substring(0, f.Name.Length - f.Extension.Length));
                    t.SelectedImageIndex = 0;
                    t.ImageIndex = 0;
                    // add it to the "master"
                    treeView1.Nodes.Add(t);
                }
            }
        }
/*
 * Author: Danny Battison
 * Contact: gabehabe@googlemail.com
 */
        public void PopulateTree(string dir, TreeNode node)
        {
            // get the information of the directory
            DirectoryInfo directory = new DirectoryInfo(dir);
            // loop through each subdirectory
            foreach (DirectoryInfo d in directory.GetDirectories())
            {
                if (d.Name.StartsWith("_"))
                    break;
                // create a new node
                TreeNode t = new TreeNode(d.Name);
                t.ImageIndex = 1;
                t.SelectedImageIndex = 1;
                t.Tag = 1;
                // populate the new node recursively
                PopulateTree(d.FullName, t);
                t.ContextMenuStrip = contextMenuStripFolder;
                node.Nodes.Add(t); // add the node to the "master" node
            }
            // lastly, loop through each file in the directory, and add these as nodes
            foreach (FileInfo f in directory.GetFiles())
            {
                if (f.Extension == ".html")
                {
                    // create a new node
                    TreeNode t = new TreeNode(f.Name.Substring(0, f.Name.Length - f.Extension.Length));
                    t.ContextMenuStrip = contextMenuStripFile;
                    DateTime oldDate;
                    DateTime.TryParse(config.get("OldDate"), out oldDate);
                    if (f.LastWriteTime < oldDate)
                    {
                        t.ForeColor = Color.Red;
                    }
                    t.Tag = 0;
                    // add it to the "master"
                    node.Nodes.Add(t);
                }
            }
        }

        private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
           // isNodeAFile(e.Node);
            if (e.Button != MouseButtons.Left) return;
                  
            if (!isNodeAFile(e.Node))
            {

                //if (e.Node.IsExpanded)
                //{
                //    bExpandNode = false;
                //    e.Node.Collapse();
                //}
                //else
                //{
                //    bExpandNode = true;
                //    e.Node.Expand();
                //}
                return;
            }
            if (openNode != e.Node)
                loadDoc(e.Node);
        }

        private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            //if (!isNodeAFile(treeView1.SelectedNode)) return;
            //loadDoc(e.Node);
        }

        private void saveToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            save();
        }

        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (config.get("AlwaysSave") == "TRUE") save();
            refreshTree();
        }


        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                File.Delete(getPath(treeView1.SelectedNode));
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString());
            }
            //refreshTree();
        }

        private void treeView1_DragDrop(object sender, DragEventArgs e)
        {
            // Unlock updates
            DragHelper.ImageList_DragLeave(this.treeView1.Handle);

            // Get drop node
            TreeNode dropNode = this.treeView1.GetNodeAt(this.treeView1.PointToClient(new Point(e.X, e.Y)));
     
            if (isNodeAFile(dropNode)) //if is file not dir
                return;

            // If drop node isn't equal to drag node, add drag node as child of drop node
            if (this.dragNode == dropNode)
                return;

            maybeSave();

            //move the file
            string src = getPath(dragNode);
            string dest = getPath(dropNode) + "\\" + dragNode.Text;
            if (isNodeAFile(dragNode))
            {
                dest += ".html";
            }

            if (File.Exists(dest))
            {
                MessageBox.Show("Cannot move file as a file with the same name exists in the destination");
                return;
            }

            if (!move(src, dest))
                return;//error

            if (isNodeAFile(dragNode))
            {
                TextReader tr = new StreamReader(dest);
                //move pictures... first find the pictures regex
                MatchCollection mc = Regex.Matches(tr.ReadToEnd(), "src=\"(.+?_[0-9]{9}.png)", RegexOptions.Singleline);
                tr.Close();
                foreach (Match m in mc)
                    if (!move(getPath(dragNode.Parent) + "\\" + m.Groups[1].Value, getPath(dropNode) + "\\" + m.Groups[1].Value))
                    {//error
                        //refreshTree();
                        //return; 
                    }
            }

            // Remove drag node from parent
            if (this.dragNode.Parent == null)
                this.treeView1.Nodes.Remove(this.dragNode);
            else
                this.dragNode.Parent.Nodes.Remove(this.dragNode);

            // Add drag node to drop node
            dropNode.Nodes.Add(this.dragNode);

            // Set drag node to null
            this.dragNode = null;

            // Disable scroll timer
            timer.Enabled = false;
        }

        private void treeView1_DragEnter(object sender, DragEventArgs e)
        {
            DragHelper.ImageList_DragEnter(this.treeView1.Handle, e.X - this.treeView1.Left,
                    e.Y - this.treeView1.Top);

            // Enable timer for scrolling dragged item
            this.timer.Enabled = true;
        }

        private void treeView1_DragLeave(object sender, EventArgs e)
        {
            DragHelper.ImageList_DragLeave(this.treeView1.Handle);

            // Disable timer for scrolling dragged item
            this.timer.Enabled = false;
        }

        private void treeView1_DragOver(object sender, DragEventArgs e)
        {
            // Compute drag position and move image
            Point formP = this.PointToClient(new Point(e.X, e.Y));
            DragHelper.ImageList_DragMove(formP.X - this.treeView1.Left, formP.Y - this.treeView1.Top);

            // Get actual drop node
            TreeNode dropNode = this.treeView1.GetNodeAt(this.treeView1.PointToClient(new Point(e.X, e.Y)));
            if (dropNode == null)
            {
                e.Effect = DragDropEffects.None;
                return;
            }

            e.Effect = DragDropEffects.Move;

            // if mouse is on a new node select it
            if (this.tempDropNode != dropNode)
            {
                DragHelper.ImageList_DragShowNolock(false);
                this.treeView1.SelectedNode = dropNode;
                DragHelper.ImageList_DragShowNolock(true);
                tempDropNode = dropNode;
            }

            // Avoid that drop node is child of drag node 
            TreeNode tmpNode = dropNode;
            while (tmpNode.Parent != null)
            {
                if (tmpNode.Parent == this.dragNode) e.Effect = DragDropEffects.None;
                tmpNode = tmpNode.Parent;
            }
        }

        private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            maybeSave();
            // Get drag node and select it
            this.dragNode = (TreeNode)e.Item;
            this.treeView1.SelectedNode = this.dragNode;

            // Reset image list used for drag image
            this.imageListDrag.Images.Clear();
            this.imageListDrag.ImageSize = new Size(this.dragNode.Bounds.Size.Width + this.treeView1.Indent, this.dragNode.Bounds.Height);

            // Create new bitmap
            // This bitmap will contain the tree node image to be dragged
            Bitmap bmp = new Bitmap(this.dragNode.Bounds.Width + this.treeView1.Indent, this.dragNode.Bounds.Height);

            // Get graphics from bitmap
            Graphics gfx = Graphics.FromImage(bmp);

            // Draw node icon into the bitmap
            gfx.DrawImage(this.imageListTreeView.Images[0], 0, 0);

            // Draw node label into bitmap
            gfx.DrawString(this.dragNode.Text,
                this.treeView1.Font,
                new SolidBrush(this.treeView1.ForeColor),
                (float)this.treeView1.Indent, 1.0f);

            // Add bitmap to imagelist
            this.imageListDrag.Images.Add(bmp);

            // Get mouse position in client coordinates
            Point p = this.treeView1.PointToClient(Control.MousePosition);

            // Compute delta between mouse position and node bounds
            int dx = p.X + this.treeView1.Indent - this.dragNode.Bounds.Left;
            int dy = p.Y - this.dragNode.Bounds.Top;

            // Begin dragging image
            if (DragHelper.ImageList_BeginDrag(this.imageListDrag.Handle, 0, dx, dy))
            {
                // Begin dragging
                this.treeView1.DoDragDrop(bmp, DragDropEffects.Move);
                // End dragging image
                DragHelper.ImageList_EndDrag();
            }
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            // get node at mouse position
            Point pt = PointToClient(Control.MousePosition);
            TreeNode node = this.treeView1.GetNodeAt(pt);

            if (node == null) return;

            // if mouse is near to the top, scroll up
            if (pt.Y < 30)
            {
                // set actual node to the upper one
                if (node.PrevVisibleNode != null)
                {
                    node = node.PrevVisibleNode;
                    if (node.PrevVisibleNode != null)
                    {
                        node = node.PrevVisibleNode;

                        // hide drag image
                        DragHelper.ImageList_DragShowNolock(false);
                        // scroll and refresh
                        node.EnsureVisible();
                        this.treeView1.Refresh();
                        // show drag image
                        DragHelper.ImageList_DragShowNolock(true);
                    }

                }
            }
            // if mouse is near to the bottom, scroll down
            else if (pt.Y > this.treeView1.Size.Height - 30)
            {
                if (node.NextVisibleNode != null)
                {
                    node = node.NextVisibleNode;

                    DragHelper.ImageList_DragShowNolock(false);
                    node.EnsureVisible();
                    this.treeView1.Refresh();
                    DragHelper.ImageList_DragShowNolock(true);
                }
            }
        }

        private void treeView1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                // Select the clicked node
                treeView1.SelectedNode = treeView1.GetNodeAt(e.X, e.Y);
            }
        }

        void deleteMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (!isNodeAFile(treeView1.SelectedNode)) return; //if not a file
                
                try
                {
                    File.Delete(getPath(treeView1.SelectedNode));
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.ToString());
                }
                // Root node's Parent property is null, so do check
                if (treeView1.SelectedNode.Parent != null)
                {
                    treeView1.SelectedNode.Parent.Nodes.Remove(treeView1.SelectedNode);
                }
                else
                {
                    treeView1.Nodes.Remove(treeView1.SelectedNode);
                }
            }
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (isNodeAFile(treeView1.SelectedNode)) return; //if not a dir
                if (treeView1.SelectedNode.Parent == null) return; //if root node

                try
                {
                    Directory.Delete(getPath(treeView1.SelectedNode), true); //recusive
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.ToString());
                }

                 //Root node's Parent property is null, so do check
                if (treeView1.SelectedNode.Parent != null)
                {
                    treeView1.SelectedNode.Parent.Nodes.Remove(treeView1.SelectedNode);
                }
                else
                {
                    treeView1.Nodes.Remove(treeView1.SelectedNode);
                }
            }
        }

        private void addFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode == null) return;
            if (isNodeAFile(treeView1.SelectedNode)) return; 
            int i = 0;
            while (Directory.Exists(getPath(treeView1.SelectedNode) + "\\NewFolder" + i) == true) i++;
            try
            {
                Directory.CreateDirectory(getPath(treeView1.SelectedNode) + "\\NewFolder" + i);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }

            TreeNode node = new TreeNode("NewFolder" + i);
            node.Tag = 1;
            node.ImageIndex = 1;
            node.SelectedImageIndex = 1;
            node.ContextMenuStrip = contextMenuStripFolder;
            treeView1.SelectedNode.Nodes.Add(node);
            treeView1.SelectedNode.Expand();
            treeView1.SelectedNode = node;
            node.BeginEdit();
        }

        private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (e.Label == null || e.Label == "")
            {
                //MessageBox.Show("no label");
                return;
            }
            if (treeView1.SelectedNode == null) return;
            if (treeView1.SelectedNode.Parent == null)
               return; //if root node
            string src = getPath(treeView1.SelectedNode);
            string dest = getPath(treeView1.SelectedNode.Parent) + "\\" + e.Label + ".html";
            //MessageBox.Show("renaming " + src + " -> " + dest);

            if (!isNodeAFile(treeView1.SelectedNode)) //if   a dir
            {
                if (Directory.Exists(getPath(treeView1.SelectedNode.Parent) + "\\" + e.Label))
                {
                    treeView1.SelectedNode.EndEdit(true);
                    return;
                }
                move(getPath(treeView1.SelectedNode), getPath(treeView1.SelectedNode.Parent) + "\\" + e.Label);
            }
            else
            {
                if (File.Exists(dest) || !File.Exists(src))
                {
                    MessageBox.Show("err renaming " + src + " -> " + dest);
                    treeView1.SelectedNode.EndEdit(true);
                    return;
                }
                
                move(src, dest);
                e.Node.Text = e.Label;
                save();
                loadDoc(e.Node); 
            }
        }

        private void treeView1_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (treeView1.SelectedNode == null) return;// treeView1.SelectedNode.EndEdit(true);
            if (treeView1.SelectedNode.Parent == null) treeView1.SelectedNode.EndEdit(true);
        }


        private void addNewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode == null) return;
            if (isNodeAFile(treeView1.SelectedNode)) return; //if a file
            int i=0;
            while (File.Exists(getPath(treeView1.SelectedNode) + "\\NewFile" + i + ".html") == true) i++;
            copy(config.get("TemplateFile"), getPath(treeView1.SelectedNode) + "\\NewFile" + i + ".html");

            TreeNode node = new TreeNode("NewFile" + i);
            node.Tag = 0;
            node.ImageIndex = 0;
            node.SelectedImageIndex = 0;
            node.ContextMenuStrip = contextMenuStripFile;
            treeView1.SelectedNode.Nodes.Add(node);
            treeView1.SelectedNode.Expand();
            treeView1.SelectedNode = node;
            node.BeginEdit();
        }

        private string getPath(TreeNode node)
        {
            TreeNode orig = node;
            string p=node.Text;
            while (node.Parent != null) 
            {
                node = node.Parent;
                p = node.Text + "\\" + p;
            }
  
            if (isNodeAFile(orig)) p = p + ".html";
            return p;
        }

        private bool isNodeAFile(TreeNode node)
        {
            if ((int)node.Tag == 0) //if   a dir
                return true;
            else
                return false;
        }

        private void maybeSave()
        {
            string currentSource = myHtmlEditor1.getSource();
            string os = myHtmlEditor1.originalSource;
            if (!myHtmlEditor1.unTouched() && os != currentSource)
            {
                if (config.get("AlwaysSave") == "TRUE")
                    save();
                else
                    if (MessageBox.Show("Save Changes?", "Caption", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
                        == DialogResult.Yes)
                        save();
            }
        }
        
        private void loadDoc(TreeNode node)
        {
            maybeSave();

            if (!isNodeAFile(node)) return;
            string s = getPath(node);
            myHtmlEditor1.loadFile(s);
            openNode = node;
            this.Text = "KnowHow - " + node.Text;
        }


        private void save()
        {
            string path;
            if (openNode == null)
            {
                //MessageBox.Show("cannot save, maybe tree has been refreshed?");
                //return;
                //if the source is the same as our template then we dont need to save it
                if (myHtmlEditor1.unTouched()) return;

                SaveDialog sd = new SaveDialog();
                if (sd.ShowDialog() == DialogResult.OK)
                {
                    path = config.get("ContentPath") + "\\" + sd.filename + ".html"; 
                }
                else
                    return;

                //add new node to root node

                TreeNode node = new TreeNode(sd.filename);
                node.Tag = 0;
                node.ImageIndex = 0;
                node.SelectedImageIndex = 0;
                node.ContextMenuStrip = contextMenuStripFile;
                rootNode.Nodes.Add(node);
                treeView1.SelectedNode = node;
                openNode = node;
                this.Text = "KnowHow - " + node.Text;
                
            }
            else
            {
                path = getPath(openNode);
                if (!File.Exists(path))
                {
                    openNode = null;
                    save();
                    return;
                }
            }

            FileInfo f = new FileInfo(path);
            string source = myHtmlEditor1.getSource();
         
            MatchCollection mc = Regex.Matches(source, "src=\"(.+?)(_[0-9]{9}.png)", RegexOptions.Singleline);
            foreach (Match m in mc)
            {
                string s = Regex.Replace(m.Groups[1].Value, ".+/", "", RegexOptions.Singleline);
                s = Regex.Replace(s, ".+\\\\", "", RegexOptions.Singleline);
                s = s.Replace("%20", " ");
                move(f.DirectoryName + "\\" + s + m.Groups[2].Value, f.DirectoryName + "\\" + openNode.Text + m.Groups[2].Value);
            }
            source = Regex.Replace(source, "src=\".+?(_[0-9]{9}.png)", "src=\"" + openNode.Text + "${1}", RegexOptions.Singleline);

            TextWriter tw = new StreamWriter(path);
            tw.Write(source);
            tw.Close();
            myHtmlEditor1.unTouched(true);
        }


        private void lastMonitorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            firstMonitor = false;
            lastMonitorToolStripMenuItem.Checked = true;
            firstMonitorToolStripMenuItem.Checked = false;
        }

        private void firstMonitorToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            firstMonitor = true;
            lastMonitorToolStripMenuItem.Checked = false;
            firstMonitorToolStripMenuItem.Checked = true;
        }

        private void trayIcon_Click(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                 myHtmlEditor1.insertScreenShot(firstMonitor);
        }

        private void splitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
        {
            if (treeView1HasFocus)
                treeView1SplitterDistance = e.SplitX;
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            config.setInt("SplitterDistance", treeView1SplitterDistance);
            config.save();
            maybeSave();
        }

        private void splitContainer1_Panel2_Enter(object sender, EventArgs e)
        {
            if (config.get("AutoHideTreeView") == "TRUE")
            {
                treeView1HasFocus = false;
                splitContainer1.SplitterDistance = myHtmlEditor1SplitterDistance;
            }
        }

        private bool copy(string src, string dest)
        {
            if (!File.Exists(src))
            {
                MessageBox.Show("Trying to copy a file and the source file does not exist: \n" + src);
                return false;
            }
            try
            {
                File.Copy(src, dest, true);
            }
            catch (Exception exc)
            {
                MessageBox.Show("Error copying file: " + exc.Message);
            }
            if (File.Exists(dest))
                return true;
            else
                return false;
        }

        private bool move(string src, string dest)
        {
            src = src.Replace("%20", " ");
            if (src == dest) return true;

            //try
            //{
            //    Directory.Move(src, dest);
            //}
            //catch (Exception exc)
            //{
            //    MessageBox.Show("Error moving file/folder: " + exc.Message);
            //    return false;
            //}

            if (src.EndsWith(".html") || src.EndsWith(".png"))
            { //if it is just a file
                try//first copy file
                {
                    File.Copy(src, dest);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error copying file/folder: " + ex.Message);
                    return false;
                }

                try//then delete
                {
                    File.Delete(src);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error deleting file/folder: " + ex.Message);
                    return false;
                }
            }
            else
            {
                if (copyDirectory(src, dest))
                    Directory.Delete(src, true);
            }
            return true;
        }

        public static bool copyDirectory(string Src, string Dst)
        {
            String[] Files;

            if (Dst[Dst.Length - 1] != Path.DirectorySeparatorChar)
                Dst += Path.DirectorySeparatorChar;
            if (!Directory.Exists(Dst)) Directory.CreateDirectory(Dst);
            Files = Directory.GetFileSystemEntries(Src);
            foreach (string Element in Files)
            {
                // Sub directories
                if (Directory.Exists(Element))
                    copyDirectory(Element, Dst + Path.GetFileName(Element));
                // Files in directory
                else
                    try
                    {
                        File.Copy(Element, Dst + Path.GetFileName(Element), true);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Error in 'CopyDirectory': " + ex.Message);
                        return false;
                    }
            }
            return true;
        }


        private void showHideTreeViewButton_Click(object sender, EventArgs e)
        {
            if (showHideTreeViewButton.Text == ">")
            {
                treeView1HasFocus = true;
                splitContainer1.SplitterDistance = treeView1SplitterDistance;
                showHideTreeViewButton.Text = "<";
                treeView1.Visible = true;
            }
            else
            {
                treeView1HasFocus = false;
                splitContainer1.SplitterDistance = 20;
                showHideTreeViewButton.Text = ">";
                treeView1.Visible = false;
            }
        }


        private void cleanupUnlinkedImagesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<string> lImagesLinkedTo = new List<string>();
            List<string> lImagesExisting = new List<string>();

            foreach (string path in config.getMany("ContentPath"))
            {
                getAllImagesExisting(path, lImagesExisting);
                getAllImageLinks(path, lImagesLinkedTo);
            }

            foreach (string s in lImagesLinkedTo)
            {
                if (lImagesExisting.Contains(s))
                    lImagesExisting.Remove(s);
            }

            string error = "";
            if (MessageBox.Show("Delete " + lImagesExisting.Count() + " file(s)?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
                        == DialogResult.Yes)
                foreach (string fileToDelete in lImagesExisting)
                {
                    try
                    {
                        File.Delete(fileToDelete);
                    }
                    catch (Exception exc)
                    {
                        error = exc.ToString();
                    }
                }
            if (error != "")
                MessageBox.Show(error);
        }


        private void getAllImagesExisting(string sDir, List<string> lImagesExisting)
        {
            try
            {
                foreach (string d in Directory.GetDirectories(sDir))
                {
                    getAllImagesExisting(d, lImagesExisting);
                }
                foreach (string f in Directory.GetFiles(sDir, "*.png"))
                {
                    lImagesExisting.Add(f);
                }
            }
            catch (System.Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
        }


        private void getAllImageLinks(string sDir, List<string> lImagesLinkedTo)
        {
            try
            {
                foreach (string d in Directory.GetDirectories(sDir))
                {
                    getAllImageLinks(d, lImagesLinkedTo);
                }
                foreach (string f in Directory.GetFiles(sDir, "*.html"))
                {
                    TextReader tr = new StreamReader(f);
                    regexSearch("src=\"(.+?[0-9]{9}.png)", tr.ReadToEnd(), lImagesLinkedTo, sDir);
                    tr.Close();
                }
            }
            catch (System.Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
        }

        private void regexSearch(string pattern, string s, List<string> resultsList, string dir)
        {
            MatchCollection mc;
            // Create a new Regex object and define the regular expression.
            Regex r = new Regex(pattern); 
            // Use the Matches method to find all matches in the input string.
            mc = r.Matches(s);
            // Loop through the match collection to retrieve all 
            // matches and positions.
            for (int i = 0; i < mc.Count; i++) 
            {
                // Add the match string to the string array.   
                resultsList.Add( dir + "\\" + mc[i].Groups[1]);
                // Record the character position where the match was found.
            }
        }

        private void refreshFolderTreeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            refreshTree();
        }


        private const int WM_NCLBUTTONDBLCLK = 0xA3;

        protected override void WndProc(ref Message m)
        {
            // defined in winuser.h
            const int WM_DRAWCLIPBOARD = 0x308;
            const int WM_CHANGECBCHAIN = 0x030D;


            switch (m.Msg)
            {
                case WM_DRAWCLIPBOARD:
                    DisplayClipboardData();
                    SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    break;

                case WM_CHANGECBCHAIN:
                    if (m.WParam == nextClipboardViewer)
                        nextClipboardViewer = m.LParam;
                    else
                        SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    break;

                case WM_NCLBUTTONDBLCLK:
                    if (alwaysOnTopDblClickTitleBarToolStripMenuItem.Checked)
                        if (bSmall)
                        {
                            bSmall = false;
                            Width = oldWidth;
                            Height = oldHeight;
                            FormBorderStyle = FormBorderStyle.Sizable;
                        }
                        else
                        {
                            bSmall = true;
                            oldWidth = Width;
                            oldHeight = Height;
                            Width = 236;
                            Height = 20;
                            FormBorderStyle = FormBorderStyle.FixedSingle;
                        } 
                    else
                        if (this.WindowState == System.Windows.Forms.FormWindowState.Maximized)
                            this.WindowState = System.Windows.Forms.FormWindowState.Normal;
                        else if (this.WindowState == System.Windows.Forms.FormWindowState.Normal)
                            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
                    return;                    
            }
            base.WndProc(ref m);
        }

        private void alwaysOnTopDblClickTitleBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (alwaysOnTopDblClickTitleBarToolStripMenuItem.CheckState == CheckState.Checked)
                TopMost = true;
            else
                TopMost = false;
        }


        void DisplayClipboardData()
        {
            if (!detectClipboardActivityToolStripMenuItem.Checked)
                return;

            try
            {
                IDataObject iData = new DataObject();
                iData = Clipboard.GetDataObject();

                if (iData.GetDataPresent(DataFormats.Bitmap))
                    myHtmlEditor1.insertClipboardData();
               /* if (iData.GetDataPresent(DataFormats.Rtf))
                    richTextBox1.Rtf = (string)iData.GetData(DataFormats.Rtf);
                else if (iData.GetDataPresent(DataFormats.Text))
                    richTextBox1.Text = (string)iData.GetData(DataFormats.Text);
                else
                    richTextBox1.Text = "[Clipboard data is not RTF or ASCII Text]";*/
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

    }
}
